package com.autumn.cloud.lock;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.redisson.config.SentinelServersConfig;
import org.redisson.config.SingleServerConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.autumn.cloud.lock.impl.DistributedLockImpl;
import com.autumn.cloud.lock.impl.MemoryReentrantLockImpl;
import com.autumn.spring.boot.properties.PropertiesConstant;
import com.autumn.util.StringUtils;

/**
 * 锁 Bean 定义
 * 
 * @author 老码农
 *
 *         2017-11-27 18:05:40
 */
@Configuration
@ConditionalOnClass(Config.class)
@EnableConfigurationProperties(RedisProperties.class)
public class AutumnLockBeanDefinition {

	/**
	 * 内存分布式锁
	 * 
	 * @return
	 */
	@Bean
	@Primary
	@ConditionalOnMissingBean(MemoryReentrantLock.class)
	public MemoryReentrantLock getMemoryReentrantLock() {
		return new MemoryReentrantLockImpl();
	}

	/**
	 * 分布式锁
	 * 
	 * @param redissonClient
	 *            分布式客户端
	 * @return
	 */
	@Bean
	@Primary
	@ConditionalOnMissingBean(DistributedLock.class)
	public DistributedLock distributedLocker(RedissonClient redissonClient) {
		return new DistributedLockImpl(redissonClient);
	}

	private final static String REDIS_SENTINEL_MASTER = PropertiesConstant.AUTUMN_CLOUD_REDIS_PROPERTIES_PREFIX
			+ ".sentinel.master";

	/**
	 * 哨兵模式
	 * 
	 * @return
	 */
	@Bean()
	@Primary
	@ConditionalOnProperty(name = REDIS_SENTINEL_MASTER)
	public RedissonClient getSentinelRedissonClient(RedisProperties properties) {
		Config config = new Config();
		SentinelServersConfig readConfig = config.useSentinelServers()
				.addSentinelAddress(properties.getSentinel().getNodes())
				.setMasterName(properties.getSentinel().getMaster()).setTimeout(properties.getTimeout())
				.setDatabase(properties.getDatabase());
		if (properties.getPool() != null) {
			readConfig = readConfig.setMasterConnectionPoolSize(properties.getPool().getMaxActive())
					.setSlaveConnectionPoolSize(properties.getPool().getMaxActive())
					.setMasterConnectionMinimumIdleSize(properties.getPool().getMinIdle())
					.setSlaveConnectionMinimumIdleSize(properties.getPool().getMinIdle());

		}
		if (!StringUtils.isNullOrBlank(properties.getPassword())) {
			readConfig = readConfig.setPassword(properties.getPassword());
		}
		return Redisson.create(config);
	}
	
	private final static String REDIS_CLUSTER_NODES = PropertiesConstant.AUTUMN_CLOUD_REDIS_PROPERTIES_PREFIX
			+ ".cluster.nodes";

	/**
	 * 集群模式
	 * 
	 * @return
	 */
	@Bean
	@Primary
	@ConditionalOnProperty(name = REDIS_CLUSTER_NODES)
	public RedissonClient getClusterRedissonClient(RedisProperties properties) {
		Config config = new Config();
		ClusterServersConfig readConfig = config.useClusterServers()
				.addNodeAddress(org.springframework.util.StringUtils.toStringArray(properties.getCluster().getNodes()))
				.setTimeout(properties.getTimeout());
		if (properties.getPool() != null) {
			readConfig = readConfig.setMasterConnectionPoolSize(properties.getPool().getMaxActive())
					.setSlaveConnectionPoolSize(properties.getPool().getMaxActive())
					.setMasterConnectionMinimumIdleSize(properties.getPool().getMinIdle())
					.setSlaveConnectionMinimumIdleSize(properties.getPool().getMinIdle());
		}
		if (!StringUtils.isNullOrBlank(properties.getPassword())) {
			readConfig = readConfig.setPassword(properties.getPassword());
		}
		return Redisson.create(config);
	}
	
	private final static String REDIS_HOST = PropertiesConstant.AUTUMN_CLOUD_REDIS_PROPERTIES_PREFIX
			+ ".host";

	/**
	 * 单机模式
	 * 
	 * @return
	 */
	@Bean
	@Primary
	@ConditionalOnProperty(name = REDIS_HOST)
	public RedissonClient getSingleRedissonClient(RedisProperties properties) {
		Config config = new Config();
		SingleServerConfig readConfig = config.useSingleServer()
				.setAddress(properties.getHost() + ":" + properties.getPort()).setTimeout(properties.getTimeout())
				.setDatabase(properties.getDatabase());
		if (properties.getPool() != null) {
			readConfig = readConfig.setConnectionPoolSize(properties.getPool().getMaxActive())
					.setConnectionMinimumIdleSize(properties.getPool().getMinIdle());
		}
		if (!StringUtils.isNullOrBlank(properties.getPassword())) {
			readConfig = readConfig.setPassword(properties.getPassword());
		}
		return Redisson.create(config);
	}

}
